// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This source set defines shared expectations for:
// 1. The packed-data format used to pass information from chrome.dll
//    to chrome_elf.dll across restarts.
// 2. The APIs exported by chrome_elf.dll to share logs of module load attempts.

#ifndef CHROME_CHROME_ELF_THIRD_PARTY_DLLS_PACKED_LIST_FORMAT_H_
#define CHROME_CHROME_ELF_THIRD_PARTY_DLLS_PACKED_LIST_FORMAT_H_

#include <stdint.h>

#include <array>
#include <string>

#include "chrome/chrome_elf/sha1/sha1.h"

namespace third_party_dlls {

// -----------------------------------------------------------------------------
// This defines the expected format for a packed list of third-party modules.
// - At offset 0: {PackedListMetadata}
// - Immediately following: {Array of PackedListModule}
// - Anything else can be stored in the rest of the file.
//
// - It's a requirement that the list be packed little-endian and also that
//   32-bit alignment == 64-bit alignment (so no handling required).
// - It's also required that the array be *sorted*. First by basename hash,
//   second by code_id hash (there can be multiple of the same basename hash).
// -----------------------------------------------------------------------------

// Subkey relative to install_static::GetRegistryPath().
extern const wchar_t kThirdPartyRegKeyName[];

// Subkey value of type REG_SZ to hold a full path to a packed-list file.
extern const wchar_t kBlFilePathRegValue[];

enum PackedListVersion : uint32_t {
  kInitialVersion = 1,
  kCurrent = kInitialVersion,
  kUnsupported
};

struct PackedListMetadata {
  // The version of the packed list format. This should always be ordered
  // first for backward compatibility purposes.
  PackedListVersion version;
  // The number of PackedListModule elements that follows the metadata in
  // the packed list.
  uint32_t module_count;
};

struct PackedListModule {
  // SHA1 of lowercase, UTF-8 basename (no path).
  elf_sha1::Digest basename_hash;
  // Code ID. Get the formatted string via GetFingerprintString(), then SHA1.
  elf_sha1::Digest code_id_hash;
  // A timestamp used for tracking "last attempted load".  Used to manage
  // lifetime of entries in the local caches.
  uint32_t time_date_stamp;
};

// Centralized utility function that takes required PE fingerprint data and
// returns a formatted fingerprint string. The caller should SHA1 hash the
// returned string.
// - This string is generated by formatting the FileHeader.TimeDateStamp
//   and OptionalHeader.SizeOfImage with the formatting string %08X%x.
// - To be used for PackedListModule.code_id_hash, IsModuleListed() and logging
//   APIs.
std::string GetFingerprintString(uint32_t time_data_stamp, uint32_t image_size);

// These structs are directly written to a storage type. Therefore the padding
// should be consistent across compilations.
static_assert(sizeof(PackedListMetadata) == 8,
              "The actual padding of the PackedListMetadata struct doesn't"
              "match the expected padding");
static_assert(sizeof(PackedListModule) == 44,
              "The actual padding of the PackedListModule struct doesn't match"
              "the expected padding");

}  // namespace third_party_dlls

#endif  // CHROME_CHROME_ELF_THIRD_PARTY_DLLS_PACKED_LIST_FORMAT_H_
